/**
  * Sample Genetic Algorithm application.
  */

#include "printf.h"
#include "bitread.h"

module GADemoC {
	uses {
		interface GeneticAlgorithm as GA;
		interface Boot;
	}
}

implementation {
	uint8_t  populationsize = 99;	// population must be in the range from [0..99]
	uint16_t numgenerations = 100;// cannot exceed 65,535
	//the unit of bit mutation is per thousand. For example, if we set the
	//bitmutation to 10, approximately every 10 out of 1k bits will be mutated
	uint16_t bitmutation=1;       

	// Static variables used by the component to keep track of where it is
	// in the genetic algorithm evaulation.
	uint16_t generation = 0;
	uint8_t i,j,display_index;
	uint16_t t0_a_population, t0_b_population, t0_fitness;
	
	// Function prototypes
	task void ga_demo();
	task void fitness_task();
	task void process_generation_task();
	task void report_statistics_task();
	task void prepare_next_generation_task();

	// For now, everything happens in the Boot.booted() event.
	event void Boot.booted() {
		// say hello
		printf("\n\n---Beginning of GA demo---\n\n");
		printfflush();

		// initialize the GA component...
		call GA.initialize_engine ( populationsize, numgenerations, bitmutation );
		printf("GA engine initialized\n");
		printfflush();

		post ga_demo();
	}

	// The genetic algorithm demo has to be implemented as a task, because
	// it takes "too long" to do in an event handler.
	task void ga_demo() {
		display_index = 0;
		i = 0;
		if ( generation < numgenerations ) {
			post fitness_task();
		}			
	}

	task void fitness_task() {
		//======================================================================
		//Fitness Evaluation
		//======================================================================
		//This is the part where we "how good" a particular combination of
		//genes is. In this simple case, we just want to maximize the number of 1's 
		//in the genes. The 1's can be for example, the number of lit LED ligths.
		//NOTE: due to memory constraints, the fitness value CANNOT(!!!) be greater
		//than 100.
		//======================================================================
		//begin: Fitness Evaluation
		//for (i=0; i < populationsize; i++) {
			t0_fitness=0;
			t0_a_population= call GA.read_t0_a_population(i); 
			t0_b_population= call GA.read_t0_b_population(i); 

			//we are evaluating the fitness on 32 bits... dividing by
			//ga.t0_a_population[i] and ga.t0_b_population[i]
			for (j=0 ; j < 16 ; j++) {
				if(bitRead(t0_a_population, j)==1) {
					t0_fitness=t0_fitness+1;
				}
				if(bitRead(t0_b_population, j)==1) {
					t0_fitness=t0_fitness+1;
				}
			}
			call GA.write_t0_fitness(i,t0_fitness);
		//} //end: Fitness Evaluation
		if (i < populationsize) {
			i++;
			post fitness_task();
		} else {
			i = 0;
			post process_generation_task();
		}
	}

	task void process_generation_task() {
    //the next steps perform the genetic optimization process
    //behind the scenes. It mates the best individuals and create the 
    //next generation with a new set of genes.   
    call GA.process_generation(generation);
    post report_statistics_task();
  }

	task void report_statistics_task() {
		call GA.report_statistics(generation,display_index);
		display_index = display_index+1;
		if (display_index < 6)
			post report_statistics_task();
		else
			post prepare_next_generation_task();
	}
	
	task void prepare_next_generation_task() {
    call GA.prepare_next_generation();
    generation=generation+1;
    post ga_demo();
 	}
}
